package upload

// @auth Crastlin@163.com
// @date 2020-10
// @update 2022-08

import (
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"io"
	"strings"
)

type AliYunOss struct {
	Driver
	Option *AliYunOption
	Client *oss.Client
	Bucket *oss.Bucket
}

type AliYunOption struct {
	Key         string
	Secret      string
	Bucket      string
	Endpoint    string
	Url         string
	SaveName    string
	AllowExtSet map[string]string
}

// InitAliYun init aliYun driver
func InitAliYun(opt *AliYunOption) Uploader {
	aliYunOss := &AliYunOss{}
	aliYunOss.Option = opt
	client, err := oss.New(opt.Endpoint, opt.Key, opt.Secret)
	if err != nil {
		panic(fmt.Sprintf("connect aliYun oss was fialed:%s", err.Error()))
	}
	aliYunOss.Client = client
	return aliYunOss
}

// CheckPath check root path
func (a *AliYunOss) CheckPath(autoCreate bool, path ...string) bool {
	bucket := a.Option.Bucket
	if len(path) > 0 {
		bucket = path[0]
	}
	if ok, _ := a.Client.IsBucketExist(bucket); !ok {
		if autoCreate {
			return a.MakeDir(bucket)
		}
		return false
	}
	var err error
	a.Bucket, err = a.Client.Bucket(bucket)
	if err != nil {
		a.errText = err.Error()
		return false
	}
	return true
}

// MakeDir make path directory
func (a *AliYunOss) MakeDir(path string) bool {
	option := []oss.Option{
		oss.ObjectACL(oss.ACLPublicRead),
	}
	err := a.Client.CreateBucket(path, option...)
	if err != nil {
		a.errText = err.Error()
		return false
	}
	a.Bucket, err = a.Client.Bucket(path)
	if err != nil {
		a.errText = err.Error()
		return false
	}
	return true
}

// Save file to path
func (a *AliYunOss) Save(file io.Reader) bool {
	if !a.CheckPath(true) {
		return false
	}
	path, fileName := a.GetSavePathInfo()
	if err := a.Bucket.PutObject(path+fileName, file); err != nil {
		a.errText = err.Error()
		return false
	}
	a.url = strings.TrimSuffix(a.Option.Url, "/") + "/" + path + fileName
	//url, err := a.Bucket.SignURL(a.Option.Key, oss.HTTPGet, 31536000000)
	//if err != nil {
	//	a.errText = err.Error()
	//	return false
	//}
	//a.url = url
	return true
}

// Remove file
func (a *AliYunOss) Remove(file string) bool {
	exists, err := a.Bucket.IsObjectExist(file)
	if !exists || err != nil {
		a.errText = err.Error()
		return false
	}
	if err := a.Bucket.DeleteObject(file); err != nil {
		a.errText = err.Error()
		return false
	}
	return true
}
